package top.kindaries.task;


import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import top.kindaries.device.Device;
import top.kindaries.utils.Ffmpeg;
import top.kindaries.utils.PropUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Task implements Runnable {

    private static final Logger logger = Logger.getLogger(Task.class);

    private boolean isRunning = false;
    // 记录线程开始时间
    private long startTime;
    // 设备信息
    private Device dev;
    // 转换可持续最大时间，达到时间则自动结束
    private long duration;
    // 设备HLS目录路径
    private String dirPath;
    // M3U8文件路径
    private String m3u8Path;

    Task(Device dev) {
        this.dev = dev;
        this.duration = PropUtil.getLong("hls.duration");
        this.dirPath = PropUtil.get("hls.folder.path") + dev.getCode();
        this.m3u8Path = PropUtil.get("hls.folder.path") + dev.getCode() + "/index.m3u8";
    }

    public Device getDev() {
        return dev;
    }

    public boolean isRunning() {
        return isRunning;
    }

    public long getDuration() {
        return duration;
    }

    public String getM3u8Path() {
        return m3u8Path;
    }

    /**
     * 设置开始时间为当前时间，以此来延长转换持续时间
     */
    public void active() {
        if (!this.isRunning) {
            //如果当前已经停止，则重新运行
            this.run();
        } else {
            //如果正在运行，则重新设置startTime
            this.startTime = System.currentTimeMillis();
        }
    }

    @Override
    public void run() {
        // 开始
        isRunning = true;
        // 创建文件夹
        createDir();
        // 运行，设置视频源和推流地址和HLS目录
        convert();
        // 运行结束，从池中移除
        TaskManager.remove(dev.getCode());
        // 删除文件夹
        deleteDir();
        // 结束
        isRunning = false;
    }

    private void convert() {
        String streamUrl = this.dev.getStreamUrl();
        // 检测流服务是否可访问
        if (StringUtils.isBlank(streamUrl) || !isConnect(streamUrl)) {
            return;
        }
        Process process = null;
        try {
            logger.debug("设备[" + this.dev.getCode() + "]：开始转码");
            process = Ffmpeg.ffmpeg(streamUrl, this.m3u8Path);
            InputStream is = process.getErrorStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line;
            this.startTime = System.currentTimeMillis();
            while (System.currentTimeMillis() - startTime < duration && (line = br.readLine()) != null) {
                if (PropUtil.getBoolean("ffmpeg.log")) {
                    logger.debug("设备[" + this.dev.getCode() + "]：" + line);
                }
            }
            // 关闭流，释放资源
            process.destroy();
        } catch (IOException e) {
            e.printStackTrace();
            // 关闭流，释放资源
            if (process != null) {
                process.destroy();
            }
        } finally {
            logger.debug("设备[" + this.dev.getCode() + "]：结束转码");
        }
    }

    /**
     * 检测指定IP+端口是否可连接
     *
     * @param streamUrl RTSP或RTMP地址
     * @return true：可连接，false：不可连接
     */
    private boolean isConnect(String streamUrl) {
        Matcher matcher = Pattern.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+):(\\d+)").matcher(streamUrl);
        String ip = matcher.find() ? matcher.group(1) : null;
        String port = matcher.find() ? matcher.group(2) : null;
        if (StringUtils.isBlank(ip) || StringUtils.isBlank(port)) {
            return true;
        }
        Socket socket = null;
        try {
            if (InetAddress.getByName(ip).isReachable(3000)) {
                socket = new Socket();
                socket.connect(new InetSocketAddress(ip, Integer.valueOf(port)));
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * 创建文件夹
     */
    private void createDir() {
        File file = new File(this.dirPath);
        file.mkdir();
    }

    /**
     * 删除文件夹
     */
    private void deleteDir() {
        deleteDir(this.dirPath);
    }

    private void deleteDir(String path) {
        File file = new File(path);
        //删除文件夹
        if (file.isFile()) {
            file.delete();
        } else {
            File[] files = file.listFiles();
            if (files == null) {
                file.delete();
            } else {
                for (int i = 0; i < files.length; i++) {
                    deleteDir(files[i].getAbsolutePath());
                }
                file.delete();
            }
        }
    }

}
